Audio II
Contents
Audio II¶
!pip install googletrans
Requirement already satisfied: googletrans in /usr/local/lib/python3.6/dist-packages (3.0.0)
Requirement already satisfied: httpx==0.13.3 in /usr/local/lib/python3.6/dist-packages (from googletrans) (0.13.3)
Requirement already satisfied: certifi in /usr/local/lib/python3.6/dist-packages (from httpx==0.13.3->googletrans) (2020.6.20)
Requirement already satisfied: chardet==3.* in /usr/local/lib/python3.6/dist-packages (from httpx==0.13.3->googletrans) (3.0.4)
Requirement already satisfied: rfc3986<2,>=1.3 in /usr/local/lib/python3.6/dist-packages (from httpx==0.13.3->googletrans) (1.4.0)
Requirement already satisfied: httpcore==0.9.* in /usr/local/lib/python3.6/dist-packages (from httpx==0.13.3->googletrans) (0.9.1)
Requirement already satisfied: hstspreload in /usr/local/lib/python3.6/dist-packages (from httpx==0.13.3->googletrans) (2020.10.6)
Requirement already satisfied: sniffio in /usr/local/lib/python3.6/dist-packages (from httpx==0.13.3->googletrans) (1.2.0)
Requirement already satisfied: idna==2.* in /usr/local/lib/python3.6/dist-packages (from httpx==0.13.3->googletrans) (2.10)
Requirement already satisfied: h2==3.* in /usr/local/lib/python3.6/dist-packages (from httpcore==0.9.*->httpx==0.13.3->googletrans) (3.2.0)
Requirement already satisfied: h11<0.10,>=0.8 in /usr/local/lib/python3.6/dist-packages (from httpcore==0.9.*->httpx==0.13.3->googletrans) (0.9.0)
Requirement already satisfied: contextvars>=2.1; python_version < "3.7" in /usr/local/lib/python3.6/dist-packages (from sniffio->httpx==0.13.3->googletrans) (2.4)
Requirement already satisfied: hyperframe<6,>=5.2.0 in /usr/local/lib/python3.6/dist-packages (from h2==3.*->httpcore==0.9.*->httpx==0.13.3->googletrans) (5.2.0)
Requirement already satisfied: hpack<4,>=3.0 in /usr/local/lib/python3.6/dist-packages (from h2==3.*->httpcore==0.9.*->httpx==0.13.3->googletrans) (3.0.0)
Requirement already satisfied: immutables>=0.9 in /usr/local/lib/python3.6/dist-packages (from contextvars>=2.1; python_version < "3.7"->sniffio->httpx==0.13.3->googletrans) (0.14)
Python. Porqué es el mejor lenguaje.
Python, el intérprete. Notebooks, jupyter, Collaboratory.
Numpy y scipy:
Presentando librerías
El sonido.
Señal de audio. El audio digital y el sonido en el mundo físico.
Gráficos librería Matplotlib:
Ploteo básico, ploteo de señales
Operaciones:
Señales más allá del seno. Suma de señales
Dominio de frecuencias
Fourier
Filtros
Otras aplicaciones
print('Hola a todos')
Hola a todos
def esc(code):
return f'\033[{code}m'
print(esc('36;1;4') + 'Bievenidos al taller introductorio de python aplicado al audio')
Bievenidos al taller introductorio de python aplicado al audio
¿Por qué python es el mejor lenguaje?¶
Batteries included Rich collection of already existing bricks of classic numerical methods, plotting or data processing tools. We don’t want to re-program the plotting of a curve, a Fourier transform or a fitting algorithm. Don’t reinvent the wheel!
Easy to learn Most scientists are not payed as programmers, neither have they been trained so. They need to be able to draw a curve, smooth a signal, do a Fourier transform in a few minutes.
Easy communication To keep code alive within a lab or a company it should be as readable as a book by collaborators, students, or maybe customers. Python syntax is simple, avoiding strange symbols or lengthy routine specifications that would divert the reader from mathematical or scientific understanding of the code.
Efficient code Python numerical modules are computationally efficient. But needless to say that a very fast code becomes useless if too much time is spent writing it. Python aims for quick development times and quick execution times.
Universal Python is a language used for many different problems. Learning Python avoids learning a new software for each new problem.
from googletrans import Translator
texto_en_ingles = """Batteries included Rich collection of already existing bricks of classic numerical methods, plotting or data processing tools. We don’t want to re-program the plotting of a curve, a Fourier transform or a fitting algorithm. Don’t reinvent the wheel!
Easy to learn Most scientists are not payed as programmers, neither have they been trained so. They need to be able to draw a curve, smooth a signal, do a Fourier transform in a few minutes.
Easy communication To keep code alive within a lab or a company it should be as readable as a book by collaborators, students, or maybe customers. Python syntax is simple, avoiding strange symbols or lengthy routine specifications that would divert the reader from mathematical or scientific understanding of the code.
Efficient code Python numerical modules are computationally efficient. But needless to say that a very fast code becomes useless if too much time is spent writing it. Python aims for quick development times and quick execution times.
Universal Python is a language used for many different problems. Learning Python avoids learning a new software for each new problem."""
translate = Translator()
texto_en_español = translate.translate(texto_en_ingles, dest='es', source = 'en')
for oracion in texto_en_español.text.split('\n'):
print('-.-')
print(oracion)
-.-
Pilas incluidas Amplia colección de ladrillos ya existentes de métodos numéricos clásicos, herramientas de trazado o procesamiento de datos. No queremos reprogramar el trazado de una curva, una transformada de Fourier o un algoritmo de ajuste. ¡No reinventes la rueda!
-.-
Fácil de aprender A la mayoría de los científicos no se les paga como programadores, ni tampoco se les ha formado para ello. Necesitan poder dibujar una curva, suavizar una señal, hacer una transformada de Fourier en unos minutos.
-.-
Comunicación sencilla Para mantener vivo el código dentro de un laboratorio o una empresa, los colaboradores, estudiantes o quizás los clientes deben poder leerlo como un libro. La sintaxis de Python es simple, evitando símbolos extraños o especificaciones de rutina largas que desviarían al lector de la comprensión matemática o científica del código.
-.-
Los módulos numéricos de código eficiente de Python son computacionalmente eficientes. Pero no hace falta decir que un código muy rápido se vuelve inútil si se dedica demasiado tiempo a escribirlo. Python apunta a tiempos de desarrollo rápidos y tiempos de ejecución rápidos.
-.-
Universal Python es un lenguaje que se usa para muchos problemas diferentes. Aprender Python evita aprender un nuevo software para cada nuevo problema.
Tipos de variables¶
# esto
string = "hola"
#los comentarios sirven para ir explicando el codigo
#integer
# numero = 2
# #float
# numero_con_coma = 2.5
# #el booleano puede ser True or False
# #boolean
# booleano = True
string
("asdjugeudoser asderusrosg oweousfouhet ijdoiwaw.'';'5'345;345';34'",
'juicio')
#algunos operadores
Estructura de datos¶
Listas, set, tuplas y diccionario
#podemos guardar los datos en listas
lista = ['a', 'b', 1, 3]
#podemos usar otros tipos de datos como
tupla = ('a', 1)
lista_de_tuplas = [('juan', 10), ('María', 18)]
triplet = ('a', 4, 5)
etc = (1, 2, 3, 4, 5, 6)
#diccionarios
diccionario = {'k' : 34}
diccionario.keys(), diccionario.values()
(dict_keys(['k']), dict_values([34]))
asd = {2 : 'asdasd'}
asd.keys()
dict_keys([2])
Indexing¶
Extraer elementos de estructura de datos
Si quisiera guardar los datos de todos mis alumnos utilizo una lista de tuplas:
Slicing¶
lista_n = [1,2,3,4,5,6,7,8,9]
# start:stop:step
# start::step
# start:stop
# start ::
# :: end
lista_n[1:6:2]
[2, 4, 6]
Funciones¶
# Escribir una función que recibe la longitud del lado de un cuadrado y retorna el área del cuadrado
def areaSquare(lado):
return lado ** 2
# Escribir una función que recibe el largo, ancho y profundidad de un ”cuboide” y retorna el área de la superficie del ”cuboide”
def surfaceAreaCuboid(largo,ancho,profundidad):
superficie = 2 * (largo * ancho + largo * profundidad + ancho * profundidad)
return superficie
Ahora llamamos a las funciones definidas anteriormente
areaSquare(3)
9
surfaceAreaCuboid(1,3,5)
46
Numpy & Scipy¶
Funciones para hacer y trabajar audio. Ambientes científicos.
An introduction to Numpy and Scipy
import numpy as np
from scipy import signal
array = np.array([[1,2,3,4,5],[1,2,3,4,4]])
array.shape
(2, 5)
x = np.array([1., -1., -2., 3])
x[x < 0] += 20
x
array([ 1., 19., 18., 3.])
El sonido.¶
El sonido en la física. El sonido en una computadora. Cómo se traduce una función continua e infinitamente densa.
\(y=A * sin({2\pi f t})\)
f = frecuencia
t = tiempo
\(w = 2*\pi*f\)
A = 1
\(y=sin({w*t})\)
El sonido digital¶
Cómo interpreta una computadora el sonido?
sampling
cuantización

#Para reproducir audio en la Jupyter N.
from IPython.display import Audio, display
#cantidad de puntos por segundo
framerate = 44100
#cinco segundos de audio
t = np.linspace(0,5,framerate*5)
f = 440
data = np.sin(2*np.pi*f*t)
data
array([ 0.00000000e+00, 6.26486079e-02, 1.25051088e-01, ...,
-1.25051088e-01, -6.26486079e-02, -1.40940660e-13])
def simple_wave(f, t, framerate, A = 1):
'''Funcion para crear una onda senoidal
inputs:
f = frecuencia, int
t = tiempo, int
A = amplitud, int
return:
wave = onda senoidal, np.array
'''
t = np.linspace(0, t, framerate*t)
return np.sin(2*np.pi*f*t)
la440 = simple_wave(440, 5, 44100)
Audio(data=la440, rate=44100)
Distancia entre notas occidentales: intervalos de media nota.
\(y=n_{0}*2^\frac{n}{12}\)
#Escala musical
n_0 = 440
notas = [440*2**(n/12) for n in range(0, 13)]
#función senoidal para cada nota
funciones_nota = []
for note_frequency in notas:
funciones_nota.append(simple_wave(note_frequency, 2, 44100))
#encontrar notas de la escala pentatónica mayor de c
# la, La#, si, do, do#, re, re#, mi, fa, fa#, sol, sol#, la
index_notas = [0,4,5,7,11,12]
scala_pentatonica = [funciones_nota[i] for i in index_notas]
Audio(data=scala_pentatonica[1], rate = 44100)
#juntamos las notas de la pentatónica
audio_concatenado = np.concatenate(scala_pentatonica)
Audio(audio_concatenado, rate=44100)
Gráficos: Librería Matplotlib¶
#Para plotear
import matplotlib.pyplot as plt
plt.style.use('seaborn-darkgrid')
%matplotlib inline
# plt.figure(figsize=(5,5))
# y = audio_concatenado
# t = np.linspace(0, 2*5, 44100*2*5)
# plt.xlim(0, 0.005)
# plt.plot(t, y)
# plt.grid()
# plt.xlabel('tiempo')
# plt.ylabel('amplitud')
# plt.show()
Operaciones entre señales¶
Más alla de las funciones trigonométricas. Operaciones entre señales.
#señal triangular
t = np.linspace(0, 1, 44100)
#2*pi*f*t
plt.xlim([0, 0.005])
triangle = signal.sawtooth(2 * np.pi * 800 * t, 0.5)
plt.plot(t, triangle)
[<matplotlib.lines.Line2D at 0x7f7175bf6e80>]
t = np.linspace(0, 1, 500, endpoint=False)
square = signal.square(2 * np.pi * 5 * t)
plt.plot(t, square)
plt.ylim(-2, 2)
(-2.0, 2.0)
t = np.linspace(0, 5, 44100*5)
w = signal.chirp(t, f0=1, f1=1500, t1=5, method='quadratic' )
plt.plot(t, w)
plt.xlim([0, 2])
plt.xlabel('t (sec)')
plt.show()
Audio(w, rate=44100)
#Armar una señal compleja con una función seno.
def simple_cos_wave(f, t, framerate, A = 1):
'''Funcion para crear una onda cos
inputs:
f = frecuencia, int
t = tiempo, int
A = amplitud, int
return:
wave = onda senoidal, np.array
'''
t = np.linspace(0, t, framerate*t)
return A*np.cos(2*np.pi*f*t)
cos_1 = simple_cos_wave(300, 5, 44100)
cos_2 = simple_cos_wave(400, 5, 44100)
sin_1 = simple_wave(500, 5, 44100)
sin_2 = simple_wave(200, 5, 44100)
suma_de_señales = cos_1 + cos_2 + sin_1 + sin_2
plt.figure()
t = np.linspace(0, 5, 44100*5)
plt.plot(t, suma_de_señales)
plt.xlim([0, 0.05])
plt.grid()
plt.show()
Audio(suma_de_señales, rate=44100)
Generando ruido
#distribución gauseana
mean = 0
std = 1
framerate = 44100
seconds = 5
num_samples = seconds*framerate
noise = np.random.normal(mean, std, size=num_samples)
x = np.linspace(0, seconds, num_samples)
plt.plot(x, noise)
plt.show()
Audio(0.5*noise, rate=framerate)
sin_noise = sin_1 + noise
Audio(sin_noise, rate = framerate)
Dominio de frecuencias¶
Fourier. análisis frecuenciar
from scipy.fft import fft, fftshift
def fourier_calculation(y, framerate):
'''Aplicando fast fourier transform'''
yf = fft(y)
N = len(y)
yf = 2.0/N *np.abs(yf[0:N//2])
xf = np.linspace(0.0, 1/2*framerate, N//2)
return yf, xf
yf, xf = fourier_calculation(w, framerate = 44100)
plt.xlim([0, 1000])
plt.plot(xf, yf)
[<matplotlib.lines.Line2D at 0x7f7174f68be0>]
yf, xf = fourier_calculation(suma_de_señales, framerate = 44100)
plt.plot(xf, yf)
plt.xlim([0, 1000])
(0.0, 1000.0)
Espectograma
a = plt.specgram(w, Fs=44100, cmap='jet')
plt.ylim([0,3000])
plt.colorbar()
plt.show()
f, t, Sxx = signal.spectrogram(w, fs=44100, nperseg=256*2, nfft=512*2)
plt.pcolormesh(t, f, Sxx, shading='gouraud', cmap='jet_r')
plt.ylim([0,2000])
plt.ylabel('Frequency [Hz]')
plt.xlabel('Time [sec]')
plt.show()
f, t, Sxx = signal.spectrogram(suma_de_señales, 44100, nperseg=256*2, nfft=512*2)
plt.pcolormesh(t, f, Sxx, shading='gouraud')
plt.ylim([0,800])
plt.ylabel('Frequency [Hz]')
plt.xlabel('Time [sec]')
plt.show()
def plot_multiple(y, fs = 44100, plot_type = 'plotly'):
'''Plotea primero la onda en dominio de tiempo, luego el espectro (FFT) y luego el espectrograma'''
#Creo el espacio para plotear, una "figura" vacia
plt.figure(figsize=(15,15))
x = np.linspace(0, len(y)/fs, len(y))
#Dividido en 3 filas y 1 columna, ploteo la onda en el 1er espacio
plt.subplot(3, 1, 1)
#plt.xlim([0, 0.005])
plt.plot(x, y)
#Pongo titulo al eje y
plt.ylabel('Amplitude')
#Grilla de fondo
plt.grid()
#FFT
#n = len(w) = duración * framerate
yf, xf = fourier_calculation(y, fs)
#Plot FFT
plt.subplot(3, 1, 2)
#Ploteo las frecuencias positivas y sus valores, con un color RGBA
plt.xlabel('Freq (Hz)')
plt.ylabel('|Y(freq)|')
plt.xlim([0,2000])
plt.plot(xf, yf)
#plot spectogram
if plot_type == 'scipy':
plt.subplot(3, 1, 3)
f, t, Sxx = signal.spectrogram(y, fs, scaling='density')
plt.pcolormesh(t, f, Sxx, shading='gouraud', cmap='jet_r')
#plt.specgram(y, Fs =fs)
plt.ylabel('Frequency [Hz]')
plt.xlabel('Time [sec]')
plt.ylim([0,2000])
plt.show()
else:
plt.subplot(3, 1, 3)
a = plt.specgram(y, Fs=fs, cmap='jet')
plt.ylim([0,3000])
plt.ylabel('Frequency [Hz]')
plt.xlabel('Time [sec]')
plt.colorbar()
plt.show()
plot_multiple(w)
Practicando con grabaciones reales
from scipy.io import wavfile
import scipy.io
# samplerate, data = wavfile.read('/content/export.wav')
# print(f"number of channels = {data.shape[1]}")
# length = data.shape[0] / samplerate
# print(f"length = {length}s")
#stereo to mono
# data = data.sum(axis=1) / 2
# plot_multiple(data, samplerate)
# from scipy.signal import savgol_filter
# yhat = savgol_filter(y, 51, 3)
#Filtrado Filtrado a través de Fourier
import numpy as np
import scipy.fftpack
plt.subplots(4, 1, figsize=(10, 10))
N = 22050
secs = 1
f = 200
x = np.linspace(0,secs, N*secs)
y = np.sin(2*np.pi*f*x) + np.random.random(N*secs) * 0.4
plt.subplot(4,1,1)
plt.plot(x[0:200],y[0:200])
w = scipy.fftpack.rfft(y)
f = scipy.fftpack.rfftfreq(N*secs, x[1]-x[0])
spectrum = w**2
plt.subplot(4,1,2)
plt.plot(f[0:1000], spectrum[0:1000])
cutoff_idx = spectrum < (spectrum.max()/5)
w2 = w.copy()
w2[cutoff_idx] = 0
spectrum2 = w2**2
plt.subplot(4,1,3)
plt.plot(f[0:1000], spectrum2[0:1000])
y2 = scipy.fftpack.irfft(w2)
plt.subplot(4,1,4)
plt.plot(x[0:200], y2[0:200])
[<matplotlib.lines.Line2D at 0x7f71767c40b8>]